<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/all.min.css" integrity="sha256-mUZM63G8m73Mcidfrv5E+Y61y7a12O5mW4ezU3bxqW4=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"tallgy.gitee.io","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":false,"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"}}</script><script src="/js/config.js"></script>
<meta name="description" content="只是一个知识的搬运工">
<meta property="og:type" content="website">
<meta property="og:title" content="tallgy&#39;s blog">
<meta property="og:url" content="http://tallgy.gitee.io/page/4/index.html">
<meta property="og:site_name" content="tallgy&#39;s blog">
<meta property="og:description" content="只是一个知识的搬运工">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="tallgy">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="http://tallgy.gitee.io/page/4/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":true,"isPost":false,"lang":"zh-CN","comments":"","permalink":"","path":"page/4/index.html","title":""}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>tallgy's blog</title>
  




  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">tallgy's blog</h1>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>







</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-overview-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">tallgy</p>
  <div class="site-description" itemprop="description">只是一个知识的搬运工</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">107</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">32</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">74</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner index posts-expand">

    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/02/10/router/router%E8%BF%9B%E9%98%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/02/10/router/router%E8%BF%9B%E9%98%B6/" class="post-title-link" itemprop="url">router进阶</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-02-10 13:51:03" itemprop="dateCreated datePublished" datetime="2022-02-10T13:51:03+08:00">2022-02-10</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/router/" itemprop="url" rel="index"><span itemprop="name">router</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <p> <strong>router进阶学习</strong></p>
<h1 id="导航守卫"><a href="#导航守卫" class="headerlink" title="导航守卫"></a>导航守卫</h1><p>​        正如其名，vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中：全局的，单个路由独享的，或者组件级的。</p>
<h2 id="全局前置守卫"><a href="#全局前置守卫" class="headerlink" title="全局前置守卫"></a>全局前置守卫</h2><p>​        你可以使用 <code>router.beforeEach</code> 注册一个全局前置守卫：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">const router = createRouter(&#123; ... &#125;)</span><br><span class="line"></span><br><span class="line">router.beforeEach((to, from) =&gt; &#123;</span><br><span class="line">  // ...</span><br><span class="line">  // 返回 false 以取消导航</span><br><span class="line">  return false</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>​        当一个导航触发时，全局前置守卫按照创建顺序调用。守卫是异步解析执行，此时导航在所有守卫 resolve 完之前一直处于<strong>等待中</strong>。</p>
<p>​        每个守卫方法接收两个参数：</p>
<ul>
<li><strong><code>to</code></strong>: 即将要进入的目标 <a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/api/#routelocationnormalized">用一种标准化的方式</a></li>
<li><strong><code>from</code></strong>: 当前导航正要离开的路由 <a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/api/#routelocationnormalized">用一种标准化的方式</a></li>
</ul>
<p>​        可以返回的值如下:</p>
<ul>
<li><code>false</code>: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮)，那么 URL 地址会重置到 <code>from</code> 路由对应的地址。</li>
<li>一个<a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/api/#routelocationraw">路由地址</a>: 通过一个路由地址跳转到一个不同的地址，就像你调用 <a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/api/#push"><code>router.push()</code></a> 一样，你可以设置诸如 <code>replace: true</code> 或 <code>name: &#39;home&#39;</code> 之类的配置。当前的导航被中断，然后进行一个新的导航，就和 <code>from</code> 一样。</li>
</ul>
<p>​        如果遇到了意料之外的情况，可能会抛出一个 <code>Error</code>。这会取消导航并且调用 <a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/api/#onerror"><code>router.onError()</code></a> 注册过的回调。</p>
<p>​        如果什么都没有，<code>undefined</code> 或返回 <code>true</code>，<strong>则导航是有效的</strong>，并调用下一个导航守卫</p>
<p>​        以上所有都同 <strong><code>async</code> 函数</strong> 和 Promise 工作方式一样：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">router.beforeEach(async (to, from) =&gt; &#123;</span><br><span class="line">  // canUserAccess() 返回 `true` 或 `false`</span><br><span class="line">  return await canUserAccess(to)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>



<h3 id="可选参数-next"><a href="#可选参数-next" class="headerlink" title="可选参数 next"></a>可选参数 next</h3><p>​        <strong>确保 <code>next</code></strong> 在任何给定的导航守卫中都被<strong>严格调用一次</strong>。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">// BAD</span><br><span class="line">router.beforeEach((to, from, next) =&gt; &#123;</span><br><span class="line">  if (to.name !== &#x27;Login&#x27; &amp;&amp; !isAuthenticated) next(&#123; name: &#x27;Login&#x27; &#125;)</span><br><span class="line">  // 如果用户未能验证身份，则 `next` 会被调用两次</span><br><span class="line">  next()</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">// GOOD</span><br><span class="line">router.beforeEach((to, from, next) =&gt; &#123;</span><br><span class="line">  if (to.name !== &#x27;Login&#x27; &amp;&amp; !isAuthenticated) next(&#123; name: &#x27;Login&#x27; &#125;)</span><br><span class="line">  else next()</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>



<h2 id="全局解析守卫"><a href="#全局解析守卫" class="headerlink" title="全局解析守卫"></a>全局解析守卫</h2><p>​        你可以用 <code>router.beforeResolve</code> 注册一个全局守卫。这和 <code>router.beforeEach</code> 类似，因为它在 <strong>每次导航</strong>时都会触发，但是确保在导航被确认之前，<strong>同时在所有组件内守卫和异步路由组件被解析之后，解析守卫就被正确调用</strong>。这里有一个例子，确保用户可以访问<a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/guide/advanced/meta.html">自定义 meta</a> 属性 <code>requiresCamera</code> 的路由：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">router.beforeResolve(async to =&gt; &#123;</span><br><span class="line">  if (to.meta.requiresCamera) &#123;</span><br><span class="line">    try &#123;</span><br><span class="line">      await askForCameraPermission()</span><br><span class="line">    &#125; catch (error) &#123;</span><br><span class="line">      if (error instanceof NotAllowedError) &#123;</span><br><span class="line">        // ... 处理错误，然后取消导航</span><br><span class="line">        return false</span><br><span class="line">      &#125; else &#123;</span><br><span class="line">        // 意料之外的错误，取消导航并把错误传给全局处理器</span><br><span class="line">        throw error</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>​        <code>router.beforeResolve</code> 是获取数据或执行任何其他操作（如果用户无法进入页面时你希望避免执行的操作）的理想位置。</p>
<h2 id="全局后置钩子"><a href="#全局后置钩子" class="headerlink" title="全局后置钩子"></a>全局后置钩子</h2><p>​        你也可以注册全局后置钩子，然而和守卫不同的是，这些钩子不会接受 <code>next</code> 函数也不会改变导航本身：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">router.afterEach((to, from) =&gt; &#123;</span><br><span class="line">  sendToAnalytics(to.fullPath)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>​        它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。</p>
<p>​        它们也反映了 <a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/guide/advanced/navigation-failures.html">navigation failures</a> 作为第三个参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">router.afterEach((to, from, failure) =&gt; &#123;</span><br><span class="line">  if (!failure) sendToAnalytics(to.fullPath)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>​        <strong>navigation failures 的属性</strong> </p>
<p>​        所有导航失败都会公开<code>to</code>和<code>from</code>属性以反映当前位置以及失败导航的目标位置：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">// trying to access the admin page</span><br><span class="line">router.push(&#x27;/admin&#x27;).then(failure =&gt; &#123;</span><br><span class="line">  if (isNavigationFailure(failure, NavigationFailureType.redirected)) &#123;</span><br><span class="line">    failure.to.path // &#x27;/admin&#x27;</span><br><span class="line">    failure.from.path // &#x27;/&#x27;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>



<h2 id="路由独享的守卫"><a href="#路由独享的守卫" class="headerlink" title="路由独享的守卫"></a>路由独享的守卫</h2><p>​        你可以直接在路由配置上定义 <code>beforeEnter</code> 守卫：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/users/:id&#x27;,</span><br><span class="line">    component: UserDetails,</span><br><span class="line">    beforeEnter: (to, from) =&gt; &#123;</span><br><span class="line">      // reject the navigation</span><br><span class="line">      return false</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>​        <code>beforeEnter</code> 守卫 <strong>只在进入路由时触发</strong>，不会在 <code>params</code>、<code>query</code> 或 <code>hash</code> 改变时触发。例如，从 <code>/users/2</code> 进入到 <code>/users/3</code> 或者从 <code>/users/2#info</code> 进入到 <code>/users/2#projects</code>。它们只有在 <strong>从一个不同的</strong> 路由导航时，才会被触发。</p>
<p>​        注意：</p>
<ul>
<li>beforeEnter 是写在routes里面，而不是组件里面。</li>
<li>其次触发时机就是进入路由的时候，但是如果没有离开路由就不会再次触发了。其中对于 参数的变化也是在路由之中的。</li>
<li>return 值的判定就是导航守卫的判定方法。</li>
</ul>
<p>​        你也可以将一个函数数组传递给 <code>beforeEnter</code>，这在为不同的路由重用守卫时很有用：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">function removeQueryParams(to) &#123;</span><br><span class="line">  if (Object.keys(to.query).length)</span><br><span class="line">    return &#123; path: to.path, query: &#123;&#125;, hash: to.hash &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">function removeHash(to) &#123;</span><br><span class="line">  if (to.hash) return &#123; path: to.path, query: to.query, hash: &#x27;&#x27; &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/users/:id&#x27;,</span><br><span class="line">    component: UserDetails,</span><br><span class="line">    beforeEnter: [removeQueryParams, removeHash],</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/about&#x27;,</span><br><span class="line">    component: UserDetails,</span><br><span class="line">    beforeEnter: [removeQueryParams],</span><br><span class="line">  &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>​        请注意，你也可以通过使用<a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/guide/advanced/meta.html">路径 meta 字段</a>和<a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#global-before-guards">全局导航守卫</a>来实现类似的行为。</p>
<h2 id="组件内的守卫"><a href="#组件内的守卫" class="headerlink" title="组件内的守卫"></a>组件内的守卫</h2><p>​        最后，你可以在路由组件内直接定义路由导航守卫(传递给路由配置的)</p>
<h3 id="可用的配置-API"><a href="#可用的配置-API" class="headerlink" title="可用的配置 API"></a>可用的配置 API</h3><p>你可以为路由组件添加以下配置：</p>
<ul>
<li><code>beforeRouteEnter</code></li>
<li><code>beforeRouteUpdate</code></li>
<li><code>beforeRouteLeave</code></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">const UserDetails = &#123;</span><br><span class="line">  template: `...`,</span><br><span class="line">  beforeRouteEnter(to, from) &#123;</span><br><span class="line">    // 在渲染该组件的对应路由被验证前调用</span><br><span class="line">    // 不能获取组件实例 `this` ！</span><br><span class="line">    // 因为当守卫执行时，组件实例还没被创建！</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeRouteUpdate(to, from) &#123;</span><br><span class="line">    // 在当前路由改变，但是该组件被复用时调用</span><br><span class="line">    // 举例来说，对于一个带有动态参数的路径 `/users/:id`，在 `/users/1` 和 `/users/2` 之间跳转的时候，</span><br><span class="line">    // 由于会渲染同样的 `UserDetails` 组件，因此组件实例会被复用。而这个钩子就会在这个情况下被调用。</span><br><span class="line">    // 因为在这种情况发生的时候，组件已经挂载好了，导航守卫可以访问组件实例 `this`</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeRouteLeave(to, from) &#123;</span><br><span class="line">    // 在导航离开渲染该组件的对应路由时调用</span><br><span class="line">    // 与 `beforeRouteUpdate` 一样，它可以访问组件实例 `this`</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        <code>beforeRouteEnter</code> 守卫 <strong>不能</strong> 访问 <code>this</code>，因为守卫在导航确认前被调用，因此即将登场的新组件还没被创建。</p>
<p>​        不过，你可以通过传一个回调给 <code>next</code> 来访问组件实例。在导航被确认的时候执行回调，并且把组件实例作为回调方法的参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">beforeRouteEnter (to, from, next) &#123;</span><br><span class="line">  next(vm =&gt; &#123;</span><br><span class="line">    // 通过 `vm` 访问组件实例</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        注意 <code>beforeRouteEnter</code> 是支持给 <code>next</code> 传递回调的唯一守卫。对于 <code>beforeRouteUpdate</code> 和 <code>beforeRouteLeave</code> 来说，<code>this</code> 已经可用了，所以<em>不支持</em> 传递回调，因为没有必要了：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">beforeRouteUpdate (to, from) &#123;</span><br><span class="line">  // just use `this`</span><br><span class="line">  this.name = to.params.name</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        这个 <strong>离开守卫</strong> 通常用来预防用户在还未保存修改前突然离开。该导航可以通过返回 <code>false</code> 来取消。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">beforeRouteLeave (to, from) &#123;</span><br><span class="line">  const answer = window.confirm(&#x27;Do you really want to leave? you have unsaved changes!&#x27;)</span><br><span class="line">  if (!answer) return false</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="使用组合式-API"><a href="#使用组合式-API" class="headerlink" title="使用组合式 API"></a>使用组合式 API</h3><p>​        如果你正在使用<a target="_blank" rel="noopener" href="https://v3.vuejs.org/guide/composition-api-setup.html#setup">组合 API 和 <code>setup</code> 函数</a>来编写组件，你可以通过 <code>onBeforeRouteUpdate</code> 和 <code>onBeforeRouteLeave</code> 分别添加 update 和 leave 守卫。 请参考<a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/guide/advanced/composition-api.html#%E5%AF%BC%E8%88%AA%E5%AE%88%E5%8D%AB">组合 API 部分</a>以获得更多细节。</p>
<h2 id="完整的导航解析流程"><a href="#完整的导航解析流程" class="headerlink" title="完整的导航解析流程"></a>完整的导航解析流程</h2><ul>
<li>导航被触发</li>
<li>在失活的组件里调用 <code>beforeRouteLeave</code> 守卫。</li>
<li>调用全局的 <code>beforeEach</code> 守卫。</li>
<li>在重用的组件里调用 <code>beforeRouteUpdate</code> 守卫(2.2+)。</li>
<li>在路由配置里调用 <code>beforeEnter</code>。</li>
<li>解析异步路由组件。</li>
<li>在被激活的组件里调用 <code>beforeRouteEnter</code>。</li>
<li>调用全局的 <code>beforeResolve</code> 守卫(2.5+)。</li>
<li>导航被确认。</li>
<li>调用全局的 <code>afterEach</code> 钩子。</li>
<li>触发 DOM 更新。</li>
<li>调用 <code>beforeRouteEnter</code> 守卫中传给 <code>next</code> 的回调函数，创建好的组件实例会作为回调函数的参数传入。</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">触发导航，失活调用组件的routeleave，调用全局的beforeEach，重用组件调用routeUpdate，调用路由配置beforeEnter，调用routeEnter，调用全局beforeResolve，调用全局afterEach，调用routeEnter的next回调函数。</span><br></pre></td></tr></table></figure>



<h1 id="路由元信息"><a href="#路由元信息" class="headerlink" title="路由元信息"></a>路由元信息</h1><p>​        有时，你可能希望将任意信息附加到路由上，如过渡名称、谁可以访问路由等。这些事情可以通过接收属性对象的<code>meta</code>属性来实现，并且它可以在路由地址和导航守卫上都被访问到。定义路由的时候你可以这样配置 <code>meta</code> 字段：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/posts&#x27;,</span><br><span class="line">    component: PostsLayout,</span><br><span class="line">    children: [</span><br><span class="line">      &#123;</span><br><span class="line">        path: &#x27;new&#x27;,</span><br><span class="line">        component: PostsNew,</span><br><span class="line">        // 只有经过身份验证的用户才能创建帖子</span><br><span class="line">        meta: &#123; requiresAuth: true &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        path: &#x27;:id&#x27;,</span><br><span class="line">        component: PostsDetail</span><br><span class="line">        // 任何人都可以阅读文章</span><br><span class="line">        meta: &#123; requiresAuth: false &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>​        首先，我们称呼 <code>routes</code> 配置中的每个路由对象为 <strong>路由记录</strong>。路由记录可以是嵌套的，因此，当一个路由匹配成功后，它可能匹配多个路由记录。</p>
<p>​        例如，根据上面的路由配置，<code>/posts/new</code> 这个 URL 将会匹配父路由记录 (<code>path: &#39;/posts&#39;</code>) 以及子路由记录 (<code>path: &#39;new&#39;</code>)。</p>
<p>​        一个路由匹配到的所有路由记录会暴露为 <code>$route</code> 对象(还有在导航守卫中的路由对象)的<code>$route.matched</code> 数组。我们需要遍历这个数组来检查路由记录中的 <code>meta</code> 字段，但是 Vue Router 还为你提供了一个 <code>$route.meta</code> 方法，它是一个非递归合并<strong>所有 <code>meta</code></strong> 字段的（从父字段到子字段）的方法。这意味着你可以简单地写</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">router.beforeEach((to, from) =&gt; &#123;</span><br><span class="line">  // 而不是去检查每条路由记录</span><br><span class="line">  // to.matched.some(record =&gt; record.meta.requiresAuth)</span><br><span class="line">  if (to.meta.requiresAuth &amp;&amp; !auth.isLoggedIn()) &#123;</span><br><span class="line">    // 此路由需要授权，请检查是否已登录</span><br><span class="line">    // 如果没有，则重定向到登录页面</span><br><span class="line">    return &#123;</span><br><span class="line">      path: &#x27;/login&#x27;,</span><br><span class="line">      // 保存我们所在的位置，以便以后再来</span><br><span class="line">      query: &#123; redirect: to.fullPath &#125;,</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>​        matched 里面的值的path是一个路由定义的样子(/about/:id) 而不是实际的url路由值。</p>
<h2 id="TypeScript"><a href="#TypeScript" class="headerlink" title="TypeScript"></a>TypeScript</h2><p>​        可以通过扩展 <code>RouteMeta</code> 接口来输入 meta 字段：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">// typings.d.ts or router.ts</span><br><span class="line">import &#x27;vue-router&#x27;</span><br><span class="line"></span><br><span class="line">declare module &#x27;vue-router&#x27; &#123;</span><br><span class="line">  interface RouteMeta &#123;</span><br><span class="line">    // 是可选的</span><br><span class="line">    isAdmin?: boolean</span><br><span class="line">    // 每个路由都必须声明</span><br><span class="line">    requiresAuth: boolean</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="数据获取"><a href="#数据获取" class="headerlink" title="数据获取"></a>数据获取</h1><p>​        有时候，进入某个路由后，需要从服务器获取数据。例如，在渲染用户信息时，你需要从服务器获取用户的数据。我们可以通过两种方式来实现：</p>
<ul>
<li><strong>导航完成之后获取</strong>：先完成导航，然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。</li>
<li><strong>导航完成之前获取</strong>：导航完成前，在路由进入的守卫中获取数据，在数据获取成功后执行导航。</li>
</ul>
<p>​        从技术角度讲，两种方式都不错 —— 就看你想要的用户体验是哪种。</p>
<h2 id="导航完成后获取数据"><a href="#导航完成后获取数据" class="headerlink" title="导航完成后获取数据"></a>导航完成后获取数据</h2><p>​        当你使用这种方式时，我们会马上导航和渲染组件，然后在组件的 created 钩子中获取数据。这让我们有机会在数据获取期间展示一个 loading 状态，还可以在不同视图间展示不同的 loading 状态。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div class=&quot;post&quot;&gt;</span><br><span class="line">    &lt;div v-if=&quot;loading&quot; class=&quot;loading&quot;&gt;Loading...&lt;/div&gt;</span><br><span class="line"></span><br><span class="line">    &lt;div v-if=&quot;error&quot; class=&quot;error&quot;&gt;&#123;&#123; error &#125;&#125;&lt;/div&gt;</span><br><span class="line"></span><br><span class="line">    &lt;div v-if=&quot;post&quot; class=&quot;content&quot;&gt;</span><br><span class="line">      &lt;h2&gt;&#123;&#123; post.title &#125;&#125;&lt;/h2&gt;</span><br><span class="line">      &lt;p&gt;&#123;&#123; post.body &#125;&#125;&lt;/p&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">export default &#123;</span><br><span class="line">  data() &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      loading: false,</span><br><span class="line">      post: null,</span><br><span class="line">      error: null,</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  created() &#123;</span><br><span class="line">    // watch 路由的参数，以便再次获取数据</span><br><span class="line">    this.$watch(</span><br><span class="line">      () =&gt; this.$route.params,</span><br><span class="line">      () =&gt; &#123;</span><br><span class="line">        this.fetchData()</span><br><span class="line">      &#125;,</span><br><span class="line">      // 组件创建完后获取数据，</span><br><span class="line">      // 此时 data 已经被 observed 了</span><br><span class="line">      &#123; immediate: true &#125;</span><br><span class="line">    )</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    fetchData() &#123;</span><br><span class="line">      this.error = this.post = null</span><br><span class="line">      this.loading = true</span><br><span class="line">      // replace `getPost` with your data fetching util / API wrapper</span><br><span class="line">      // 用你的数据获取 util 或 API 替换 `getPost`</span><br><span class="line">      getPost(this.$route.params.id, (err, post) =&gt; &#123;</span><br><span class="line">        this.loading = false</span><br><span class="line">        if (err) &#123;</span><br><span class="line">          this.error = err.toString()</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">          this.post = post</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        简单来说就是创建了 loading error post 三个状态，然后再created的时候创建监听（理由是创建的监听参数的变化，可以重复触发。否则在参数变化时使用的复用将不会触发改变。）使用 immediate 为true，立刻触发。再调用fetch方法。然后再进行调用时设置post，error为null，作用是避免复用的影响，设置loading为true，然后便是正常的获取数据并显示了。</p>
<h2 id="导航完成前获取数据"><a href="#导航完成前获取数据" class="headerlink" title="导航完成前获取数据"></a>导航完成前获取数据</h2><p>​        通过这种方式，我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 <code>beforeRouteEnter</code> 守卫中获取数据，当数据获取成功后只调用 <code>next</code> 方法：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">export default &#123;</span><br><span class="line">  data() &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      post: null,</span><br><span class="line">      error: null,</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeRouteEnter(to, from, next) &#123;</span><br><span class="line">    getPost(to.params.id, (err, post) =&gt; &#123;</span><br><span class="line">      next(vm =&gt; vm.setData(err, post))</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  // 路由改变前，组件就已经渲染完了</span><br><span class="line">  // 逻辑稍稍不同</span><br><span class="line">  async beforeRouteUpdate(to, from) &#123;</span><br><span class="line">    this.post = null</span><br><span class="line">    try &#123;</span><br><span class="line">      this.post = await getPost(to.params.id)</span><br><span class="line">    &#125; catch (error) &#123;</span><br><span class="line">      this.error = error.toString()</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        这个就是在 beforeRouteEnter里面调用了异步请求，然后再获取到数据之后将数据使用next回调进行调用。同时再beforeRouteUpdate进行更新时使用了es6的async 和 await方法。同时设置this.post为null，然后在调用getPost方法获取数据返回给post。</p>
<p>​        在为后面的视图获取数据时，用户会停留在当前的界面，因此建议在数据获取期间，显示一些进度条或者别的指示。如果数据获取失败，同样有必要展示一些全局的错误提醒。</p>
<h1 id="组合式API"><a href="#组合式API" class="headerlink" title="组合式API"></a>组合式API</h1><h2 id="在-setup-中访问路由和当前路由"><a href="#在-setup-中访问路由和当前路由" class="headerlink" title="在 setup 中访问路由和当前路由"></a>在 setup 中访问路由和当前路由</h2><p>​        因为我们在 <code>setup</code> 里面没有访问 <code>this</code>，所以我们不能再直接访问 <code>this.$router</code> 或 <code>this.$route</code>。作为替代，我们使用 <code>useRouter</code> 函数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">import &#123; useRouter, useRoute &#125; from &#x27;vue-router&#x27;</span><br><span class="line"></span><br><span class="line">export default &#123;</span><br><span class="line">  setup() &#123;</span><br><span class="line">  	// useRouter 和 useRoute 是一个方法。返回一个route 和 router 的一个对象</span><br><span class="line">  	// route 是当前路由的信息， router 主要是原型的方法。和 全局路由信息。</span><br><span class="line">    const router = useRouter()</span><br><span class="line">    const route = useRoute()</span><br><span class="line"></span><br><span class="line">	// </span><br><span class="line">    function pushWithQuery(query) &#123;</span><br><span class="line">      router.push(&#123;</span><br><span class="line">        name: &#x27;search&#x27;,</span><br><span class="line">        query: &#123;</span><br><span class="line">          ...route.query,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        <code>route</code> 对象是一个响应式对象，所以它的任何属性都可以被监听，但你应该<strong>避免监听整个 <code>route</code></strong> 对象：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">import &#123; useRoute &#125; from &#x27;vue-router&#x27;</span><br><span class="line"></span><br><span class="line">export default &#123;</span><br><span class="line">  setup() &#123;</span><br><span class="line">    const route = useRoute()</span><br><span class="line">    const userData = ref()</span><br><span class="line"></span><br><span class="line">    // 当参数更改时获取用户信息</span><br><span class="line">    watch(</span><br><span class="line">      () =&gt; route.params,</span><br><span class="line">      async newParams =&gt; &#123;</span><br><span class="line">        userData.value = await fetchUser(newParams.id)</span><br><span class="line">      &#125;</span><br><span class="line">    )</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        请注意，在模板中我们仍然可以访问 <code>$router</code> 和 <code>$route</code>，所以不需要在 <code>setup</code> 中返回 <code>router</code> 或 <code>route</code>。</p>
<h2 id="导航守卫-1"><a href="#导航守卫-1" class="headerlink" title="导航守卫"></a>导航守卫</h2><p>​        </p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/02/07/router/router%E5%9F%BA%E7%A1%80/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/02/07/router/router%E5%9F%BA%E7%A1%80/" class="post-title-link" itemprop="url">router基础</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-02-07 18:41:53" itemprop="dateCreated datePublished" datetime="2022-02-07T18:41:53+08:00">2022-02-07</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/router/" itemprop="url" rel="index"><span itemprop="name">router</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="router-的基础学习"><a href="#router-的基础学习" class="headerlink" title="router 的基础学习"></a>router 的基础学习</h1><h2 id="router-的基本使用"><a href="#router-的基本使用" class="headerlink" title="router 的基本使用"></a>router 的基本使用</h2><h3 id="HTML"><a href="#HTML" class="headerlink" title="HTML"></a>HTML</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;!--使用 router-link 组件进行导航 --&gt;</span><br><span class="line">&lt;!--通过传递 `to` 来指定链接 --&gt;</span><br><span class="line">&lt;!--`&lt;router-link&gt;` 将呈现一个带有正确 `href` 属性的 `&lt;a&gt;` 标签--&gt;</span><br><span class="line">&lt;router-link to=&quot;/&quot;&gt;Go to Home&lt;/router-link&gt;</span><br><span class="line">&lt;router-link to=&quot;/about&quot;&gt;Go to About&lt;/router-link&gt;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 路由出口 --&gt;</span><br><span class="line">&lt;!-- 路由匹配到的组件将渲染在这里 --&gt;</span><br><span class="line">&lt;router-view&gt;&lt;/router-view&gt;</span><br></pre></td></tr></table></figure>

<h3 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123; path: &#x27;/&#x27;, component: Home &#125;,</span><br><span class="line">  &#123; path: &#x27;/about&#x27;, component: About &#125;,</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line">const router = VueRouter.createRouter(&#123;</span><br><span class="line">  // 4. 内部提供了 history 模式的实现。为了简单起见，我们在这里使用 hash 模式。</span><br><span class="line">  history: VueRouter.createWebHashHistory(),</span><br><span class="line">  routes, // `routes: routes` 的缩写</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.use(router)</span><br></pre></td></tr></table></figure>

<p>​        通过JavaScript进行调用</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">this.$router.push(&#x27;/login&#x27;)</span><br></pre></td></tr></table></figure>

<p>​        请记住，<code>this.$router</code> 与直接使用通过 <code>createRouter</code> 创建的 <code>router</code> 实例完全相同。我们使用 <code>this.$router</code> 的原因是，我们不想在每个需要操作路由的组件中都导入路由。</p>
<h2 id="动态路由匹配"><a href="#动态路由匹配" class="headerlink" title="动态路由匹配"></a>动态路由匹配</h2><p>​        我们可以使用一个动态字段来进行实现，我们称之为 路径参数。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  // 动态字段以冒号开始</span><br><span class="line">  &#123; path: &#x27;/users/:id&#x27;, component: User &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>​        现在像 <code>/users/johnny</code> 和 <code>/users/jolyne</code> 这样的 URL 都会映射到同一个路由。</p>
<p>​        它的 <em>params</em> 的值将在每个组件中以 <code>this.$route.params</code> 的形式暴露出来。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">this.$route.params.id</span><br></pre></td></tr></table></figure>

<p>通过这个方式添加的参数是直接会放在url路径里面的，所以不会因为刷新而消失</p>
<h3 id="相应路由参数的变化"><a href="#相应路由参数的变化" class="headerlink" title="相应路由参数的变化"></a>相应路由参数的变化</h3><p>​        当用户从 <code>/users/johnny</code> 导航到 <code>/users/jolyne</code> 时，<strong>相同的组件实例将被重复使用</strong>。因为两个路由都渲染同个组件，比起销毁再创建，复用则显得更加高效。<strong>不过，这也意味着组件的生命周期钩子不会被调用</strong>。</p>
<p>​        要对同一个组件中参数的变化做出响应的话，你可以简单地 watch <code>$route</code> 对象上的任意属性，在这个场景中，就是 <code>$route.params </code> </p>
<p><strong>方法一：我们可以使用 watch 事件，对params进行监听：</strong> </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">const User = &#123;</span><br><span class="line">  template: &#x27;...&#x27;,</span><br><span class="line">  created() &#123;</span><br><span class="line">    this.$watch(</span><br><span class="line">      () =&gt; this.$route.params,</span><br><span class="line">      (toParams, previousParams) =&gt; &#123;</span><br><span class="line">        // 对路由变化做出响应...</span><br><span class="line">      &#125;</span><br><span class="line">    )</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        我们逐行分析，首先，this.$watch 是vue的一个 vm.$watch 的方法。其实就是 watch 属性。</p>
<p>​        然后，我们得知道 this.$watch 的参数，才知道这个作用是什么。</p>
<ul>
<li>参数一： 是一个string类型，是一个表达式。或者是一个函数。通过判断返回值的变化来进行处理。</li>
<li>参数二：是一个调用的方法。对应的两个参数是 oldValue 和 newValue。同时会返回一个 unwatch 的方法。调用后将取消监听。</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var unwatch = vm.$watch(&#x27;a&#x27;, cb)</span><br><span class="line">// 之后取消观察</span><br><span class="line">unwatch()</span><br></pre></td></tr></table></figure>



<p><strong>方法二：使用路由守卫 beforeRouterUpdate</strong>：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">const User = &#123;</span><br><span class="line">  template: &#x27;...&#x27;,</span><br><span class="line">  async beforeRouteUpdate(to, from) &#123;</span><br><span class="line">    // 对路由变化做出响应...</span><br><span class="line">    this.userData = await fetchUser(to.params.id)</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p><strong>我们分析两个的区别</strong>：</p>
<p>简述区别：下面的说法很长，并且总结的可能不对：</p>
<ul>
<li>$watch 是通过监听的方式进行的监听，所以，只要组件没有被销毁的情况下，监听就有效。所以再从监听组件跳出其他组件时会触发。</li>
<li>路由守卫 beforeRouteUpdate 是需要在路由内部的参数变化才会触发。对于跳转去其他路由和从其他路由跳转回来都不会触发。</li>
</ul>
<p>第一个：是利用路由的复用原因，所以使用watch来监听参数的变化，通过参数的变化，来表示里面的修改。</p>
<p>​        同时使用 watch 进行监听，对于跳转去其他路由，也会进入监听的判断。</p>
<p>​        为什么跳出去的时候会进行一次判断。虽然我们可以知道，监听的是 this.$route.params。这个是一个全局且是一个唯一的对象。</p>
<p>​        就是说。在当前项目里面的params。那么就会是这一个，那么确实，监听有效是应该的。但是我们更应该思考。这个监听我们是在这个里面进行的创建，那么在这个组件被移除之后，监听也会被移除。所以按理，跳转出去之后是不会触发监听的。</p>
<p>​        结果也算是半个很像。因为在跳转出去之后的每一次都不会触发监听。但是，在跳转出去的那一次也会触发。并把目的路由也找到。</p>
<p>​        说明了路由是在destroy之前进行了判断跳转修改了。</p>
<p>第二个：是使用的路由守卫。通过每次跳转路由时，会经过的路由守卫来判断。</p>
<p>​        通过使用路由守卫来进行判断的。跳转去其他路由，并不会触发路由守卫。</p>
<p>​        但是跳转时机 beforeRouteUpdate 会在监听之前进行输出。</p>
<p>​        那么我们就需要思考了，首先对于 before路由守卫 会在监听前进行调用执行。那么按理说。应该会和监听的输出基本一致。</p>
<p>​        但是最终就是，对于跳转出去的路由并不会触发路由守卫</p>
<p>​        同时我们通过断点调试发现。before路由守卫 执行之后，浏览器的url才会进行改变。意思就是说。watch事件的时候，浏览器的url已经发生改变了。</p>
<h3 id="捕获路由"><a href="#捕获路由" class="headerlink" title="捕获路由"></a>捕获路由</h3><p>​        简单来说，我们可以通过加入正则表达式来进行。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  // 将匹配所有内容并将其放在 `$route.params.pathMatch` 下</span><br><span class="line">  &#123; path: &#x27;/:pathMatch(.*)*&#x27;, name: &#x27;NotFound&#x27;, component: NotFound &#125;,</span><br><span class="line">  // 将匹配以 `/user-` 开头的所有内容，并将其放在 `$route.params.afterUser` 下</span><br><span class="line">  &#123; path: &#x27;/user-:afterUser(.*)&#x27;, component: UserGeneric &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>​        这里使用了 正则表达式的语法。然后意思就是 :pathMatch 里面的内容要满足正则表达式，对于不满足的。那么就不会进入这个路由。</p>
<p>​        同时使用匹配的，对于 /:path 可以匹配到 /a /a/b 这种多层的嵌套。但是前提是，没有其他的path选择。</p>
<p>​        router 使用的路径匹配算法，其灵感来自于 express</p>
<h2 id="路由的匹配语法"><a href="#路由的匹配语法" class="headerlink" title="路由的匹配语法"></a>路由的匹配语法</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// /:orderId -&gt; 仅匹配数字</span><br><span class="line">&#123; path: &#x27;/:orderId(\\d+)&#x27; &#125;,</span><br><span class="line">// /:productName -&gt; 匹配其他任何内容</span><br><span class="line">&#123; path: &#x27;/:productName&#x27; &#125;,</span><br></pre></td></tr></table></figure>

<p>​        现在，转到 <code>/25</code> 将匹配 <code>/:orderId</code>，其他情况将会匹配 <code>/:productName</code>。<code>routes</code> 数组的顺序并不重要!</p>
<blockquote>
<p>TIP</p>
<p>确保**转义反斜杠( <code>\</code> )**，就像我们对 <code>\d</code> (变成<code>\\d</code>)所做的那样，在 JavaScript 中实际传递字符串中的反斜杠字符。</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123; path: &#x27;/:pathMatch&#x27;, component: About &#125;</span><br><span class="line"></span><br><span class="line">这样匹配将不能匹配到 / /asd/s</span><br><span class="line">因为这个正则是默认的([^/]+)，^代表了不匹配括号里面的。然后 +，代表了至少需要匹配到一个以上。所以对于上面的，不会被匹配到。</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123; path: &#x27;/:p(.*)&#x27; &#125; </span><br><span class="line">同时我们自己也可以进行覆盖。</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123; path: &#x27;/:p*&#x27; &#125;</span><br><span class="line"></span><br><span class="line">可以匹配到 / /as/a /sa/s</span><br><span class="line">同时我们也可以 把 p 进行正则。那么这样的话，可以多次进行匹配。注意这样生成的params是一个数组。而不是一个字符串。</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  // 仅匹配数字</span><br><span class="line">  // 匹配 /1, /1/2, 等</span><br><span class="line">  &#123; path: &#x27;/:chapters(\\d+)+&#x27; &#125;,</span><br><span class="line">  // 匹配 /, /1, /1/2, 等</span><br><span class="line">  &#123; path: &#x27;/:chapters(\\d+)*&#x27; &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>​        同时也可以使用  <strong>?</strong> 来代表可选参数。当然使用 * 这个也是可选的。但是使用 ？是0或者1个，不会出现重复。</p>
<p>​        <strong>路径的排名</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://paths.esm.dev/?p=AAMeJSyAwR4UbFDAFxAcAGAIJXMAAA..</span><br></pre></td></tr></table></figure>

<p>​        这是一个路径的排名工具，作用的话，我认为应该是通过计算分数。路径的匹配会通过分数进行排序来匹配。</p>
<h2 id="嵌套路由"><a href="#嵌套路由" class="headerlink" title="嵌套路由"></a>嵌套路由</h2><p>​        简单来说就是，router-view 是会渲染 的顶层的路由组件，但是对于组件内部也使用了路由的。我们就可以使用路由嵌套了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/user/:id&#x27;,</span><br><span class="line">    component: User,</span><br><span class="line">    children: [</span><br><span class="line">      &#123;</span><br><span class="line">        // 当 /user/:id/profile 匹配成功</span><br><span class="line">        // UserProfile 将被渲染到 User 的 &lt;router-view&gt; 内部</span><br><span class="line">        path: &#x27;profile&#x27;,</span><br><span class="line">        component: UserProfile,</span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        // 当 /user/:id/posts 匹配成功</span><br><span class="line">        // UserPosts 将被渲染到 User 的 &lt;router-view&gt; 内部</span><br><span class="line">        path: &#x27;posts&#x27;,</span><br><span class="line">        component: UserPosts,</span><br><span class="line">      &#125;,</span><br><span class="line">    ],</span><br><span class="line">  &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>​        简单来说就是我们会对于匹配成功的子路由，然后会在 User组件里面的 router-view 进行渲染。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">children: [</span><br><span class="line">    // 当 /user/:id 匹配成功</span><br><span class="line">    // UserHome 将被渲染到 User 的 &lt;router-view&gt; 内部</span><br><span class="line">    &#123; path: &#x27;&#x27;, component: UserHome &#125;,</span><br><span class="line"></span><br><span class="line">    // ...其他子路由</span><br><span class="line">],</span><br></pre></td></tr></table></figure>

<p>​        同时我们可以使用一个空的 path 来代表子路由的home。但是记住，空的path只是代表匹配了 /user/:id 但是对于 /user/:id/asd 虽然没有在子路由匹配成功。但是进入了子路由的，这个不会被匹配到。</p>
<h2 id="编程式导航"><a href="#编程式导航" class="headerlink" title="编程式导航"></a>编程式导航</h2><p>​        <strong>在 Vue 实例中，你可以通过 <code>$router</code> 访问路由实例。因此你可以调用 <code>this.$router.push</code>。</strong></p>
<p>​        当你点击 <code>&lt;router-link&gt;</code> 时，内部会调用这个方法，所以点击     <code>&lt;router-link :to=&quot;...&quot;&gt;</code> 相当于调用 <code>router.push(...)</code> </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">// 字符串路径</span><br><span class="line">router.push(&#x27;/users/eduardo&#x27;)</span><br><span class="line"></span><br><span class="line">// 带有路径的对象</span><br><span class="line">router.push(&#123; path: &#x27;/users/eduardo&#x27; &#125;)</span><br><span class="line"></span><br><span class="line">// 命名的路由，并加上参数，让路由建立 url</span><br><span class="line">router.push(&#123; name: &#x27;user&#x27;, params: &#123; username: &#x27;eduardo&#x27; &#125; &#125;)</span><br><span class="line"></span><br><span class="line">// 带查询参数，结果是 /register?plan=private</span><br><span class="line">router.push(&#123; path: &#x27;/register&#x27;, query: &#123; plan: &#x27;private&#x27; &#125; &#125;)</span><br><span class="line"></span><br><span class="line">// 带 hash，结果是 /about#team</span><br><span class="line">router.push(&#123; path: &#x27;/about&#x27;, hash: &#x27;#team&#x27; &#125;)</span><br></pre></td></tr></table></figure>

<p>​        <strong>但是注意</strong>，如果提供了 <code>path</code>，<code>params</code> 会被忽略，上述例子中的 <code>query</code> 并不属于这种情况。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const username = &#x27;eduardo&#x27;</span><br><span class="line">// 我们可以手动建立 url，但我们必须自己处理编码</span><br><span class="line">router.push(`/user/$&#123;username&#125;`) // -&gt; /user/eduardo</span><br><span class="line">// 同样</span><br><span class="line">router.push(&#123; path: `/user/$&#123;username&#125;` &#125;) // -&gt; /user/eduardo</span><br><span class="line">// 如果可能的话，使用 `name` 和 `params` 从自动 URL 编码中获益</span><br><span class="line">router.push(&#123; name: &#x27;user&#x27;, params: &#123; username &#125; &#125;) // -&gt; /user/eduardo</span><br><span class="line">// `params` 不能与 `path` 一起使用</span><br><span class="line">router.push(&#123; path: &#x27;/user&#x27;, params: &#123; username &#125; &#125;) // -&gt; /user</span><br></pre></td></tr></table></figure>

<p>​        由于属性 <code>to</code> 与 <code>router.push</code> 接受的对象种类相同，所以两者的规则完全相同。</p>
<p>​         <code>router.push</code> 和所有其他导航方法都会返回一个 <em>Promise</em>，让我们可以等到导航完成后才知道是成功还是失败。我们将在 <a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/guide/advanced/navigation-failures.html">Navigation Handling</a> 中详细介绍。</p>
<h3 id="替换当前位置"><a href="#替换当前位置" class="headerlink" title="替换当前位置"></a>替换当前位置</h3><p>​        使用 replace 来进行跳转，唯一不同的是，它在导航时不会向 history 添加新记录，正如它的名字所暗示的那样——它取代了当前的条目。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;router-link :to=&quot;...&quot; replace&gt;	</span><br><span class="line">router.replace(...)</span><br></pre></td></tr></table></figure>

<p>​        也可以直接在传递给 <code>router.push</code> 的 <code>routeLocation</code> 中增加一个属性 <code>replace: true</code> </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">router.push(&#123; path: &#x27;/home&#x27;, replace: true &#125;)</span><br><span class="line">// 相当于</span><br><span class="line">router.replace(&#123; path: &#x27;/home&#x27; &#125;)</span><br></pre></td></tr></table></figure>



<h3 id="横跨历史"><a href="#横跨历史" class="headerlink" title="横跨历史"></a>横跨历史</h3><p>​        该方法采用一个整数作为参数，表示在历史堆栈中前进或后退多少步，类似于 <code>window.history.go(n)</code>。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">// 向前移动一条记录，与 router.forward() 相同</span><br><span class="line">router.go(1) 右箭头</span><br><span class="line"></span><br><span class="line">// 返回一条记录，与router.back() 相同</span><br><span class="line">router.go(-1) 左箭头</span><br><span class="line"></span><br><span class="line">// 前进 3 条记录</span><br><span class="line">router.go(3)</span><br><span class="line"></span><br><span class="line">// 如果没有那么多记录，静默失败</span><br><span class="line">router.go(-100)</span><br><span class="line">router.go(100)</span><br></pre></td></tr></table></figure>



<h3 id="篡改历史"><a href="#篡改历史" class="headerlink" title="篡改历史"></a>篡改历史</h3><p>​        你可能已经注意到，<code>router.push</code>、<code>router.replace</code> 和 <code>router.go</code> 是 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/en-US/docs/Web/API/History"><code>window.history.pushState</code>、<code>window.history.replaceState</code> 和 <code>window.history.go</code></a> 的翻版，它们确实模仿了 <code>window.history</code> 的 API。</p>
<p>​        同时我刚刚进行了测试，发现了 pushState并没有刷新浏览器，但是更新了url，所以这就是router模仿的。对，使用history.go 以及使用 replaceState 都没有进行刷新，仅仅只是修改了url，因为这个是一个同源的方法。对于不同源的处理会出错。</p>
<h2 id="命名路由"><a href="#命名路由" class="headerlink" title="命名路由"></a>命名路由</h2><p>​        除了 <code>path</code> 之外，你还可以为任何路由提供 <code>name</code>。这有以下优点：</p>
<ul>
<li>没有硬编码的 URL</li>
<li><code>params</code> 的自动编码/解码。</li>
<li>防止你在 url 中出现打字错误。</li>
<li>绕过路径排序（如显示一个）</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/user/:username&#x27;,</span><br><span class="line">    name: &#x27;user&#x27;,</span><br><span class="line">    component: User</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;router-link :to=&quot;&#123; name: &#x27;user&#x27;, params: &#123; username: &#x27;erina&#x27; &#125;&#125;&quot;&gt;</span><br><span class="line">  User</span><br><span class="line">&lt;/router-link&gt;</span><br><span class="line"></span><br><span class="line">路由将导航到路径 `/user/erina`。</span><br></pre></td></tr></table></figure>



<h2 id="命名视图"><a href="#命名视图" class="headerlink" title="命名视图"></a>命名视图</h2><p>​        有时候想同时 (同级) 展示多个视图，而不是嵌套展示，例如创建一个布局，有 <code>sidebar</code> (侧导航) 和 <code>main</code> (主内容) 两个视图，这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图，而不是只有一个单独的出口。如果 <code>router-view</code> 没有设置名字，那么默认为 <code>default</code>。</p>
<p>​        简单来说就是，想要存在多个同级的router-view，可以使用命名视图， 默认名字为 default</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;router-view class=&quot;view left-sidebar&quot; name=&quot;LeftSidebar&quot;&gt;&lt;/router-view&gt;</span><br><span class="line">&lt;router-view class=&quot;view main-content&quot;&gt;&lt;/router-view&gt;</span><br><span class="line">&lt;router-view class=&quot;view right-sidebar&quot; name=&quot;RightSidebar&quot;&gt;&lt;/router-view&gt;</span><br></pre></td></tr></table></figure>

<p>​        一个视图使用一个组件渲染，因此对于同个路由，多个视图就需要多个组件。确保正确使用 <code>components</code> 配置 (带上 <strong>s</strong>)：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">const router = createRouter(&#123;</span><br><span class="line">  history: createWebHashHistory(),</span><br><span class="line">  routes: [</span><br><span class="line">    &#123;</span><br><span class="line">      path: &#x27;/&#x27;,</span><br><span class="line">      components: &#123;</span><br><span class="line">        default: Home,</span><br><span class="line">        // LeftSidebar: LeftSidebar 的缩写</span><br><span class="line">        LeftSidebar,</span><br><span class="line">        // 它们与 `&lt;router-view&gt;` 上的 `name` 属性匹配</span><br><span class="line">        RightSidebar,</span><br><span class="line">      &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>​        当然也是可以不用全部路由都要渲染的。</p>
<h3 id="命名嵌套视图"><a href="#命名嵌套视图" class="headerlink" title="命名嵌套视图"></a>命名嵌套视图</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  path: &#x27;/settings&#x27;,</span><br><span class="line">  // 你也可以在顶级路由就配置命名视图</span><br><span class="line">  component: UserSettings,</span><br><span class="line">  children: [&#123;</span><br><span class="line">    path: &#x27;emails&#x27;,</span><br><span class="line">    component: UserEmailsSubscriptions</span><br><span class="line">  &#125;, &#123;</span><br><span class="line">    path: &#x27;profile&#x27;,</span><br><span class="line">    components: &#123;</span><br><span class="line">      default: UserProfile,</span><br><span class="line">      helper: UserProfilePreview</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="重定向和别名"><a href="#重定向和别名" class="headerlink" title="重定向和别名"></a>重定向和别名</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">使用路由</span><br><span class="line">const routes = [&#123; path: &#x27;/home&#x27;, redirect: &#x27;/&#x27; &#125;]</span><br><span class="line"></span><br><span class="line">使用命名的路由</span><br><span class="line">const routes = [&#123; path: &#x27;/home&#x27;, redirect: &#123; name: &#x27;homepage&#x27; &#125; &#125;]</span><br><span class="line"></span><br><span class="line">通过一个方法，返回一个重定向目标</span><br><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    // /search/screens -&gt; /search?q=screens</span><br><span class="line">    path: &#x27;/search/:searchText&#x27;,</span><br><span class="line">    redirect: to =&gt; &#123;</span><br><span class="line">      // 方法接收目标路由作为参数</span><br><span class="line">      // return 重定向的字符串路径/路径对象</span><br><span class="line">      return &#123; path: &#x27;/search&#x27;, query: &#123; q: to.params.searchText &#125; &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/search&#x27;,</span><br><span class="line">    // ...</span><br><span class="line">  &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>​        请注意，**<a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/guide/advanced/navigation-guards.html">导航守卫</a>并没有应用在跳转路由上，而仅仅应用在其目标上**。在上面的例子中，在 <code>/home</code> 路由中添加 <code>beforeEnter</code> 守卫不会有任何效果。</p>
<p>​        在写 <code>redirect</code> 的时候，可以省略 <code>component</code> 配置，因为它从来没有被直接访问过，所以没有组件要渲染。唯一的例外是<a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/guide/essentials/nested-routes.html">嵌套路由</a>：如果一个路由记录有 <code>children</code> 和 <code>redirect</code> 属性，它也应该有 <code>component</code> 属性。</p>
<h3 id="相对重定向"><a href="#相对重定向" class="headerlink" title="相对重定向"></a>相对重定向</h3><p>​        也可以重定向到相对位置，这里没有理解</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/users/:id/posts&#x27;,</span><br><span class="line">    redirect: to =&gt; &#123;</span><br><span class="line">      // 方法接收目标路由作为参数</span><br><span class="line">      // return 重定向的字符串路径/路径对象</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>



<h3 id="别名"><a href="#别名" class="headerlink" title="别名"></a>别名</h3><p>​        重定向是指当用户访问 <code>/home</code> 时，URL 会被 <code>/</code> 替换，然后匹配成 <code>/</code>。那么什么是别名呢？</p>
<p>​         <strong>将 <code>/</code> 别名为 <code>/home</code>，意味着当用户访问 <code>/home</code> 时，URL 仍然是 <code>/home</code>，但会被匹配为用户正在访问 <code>/</code>。</strong> </p>
<p>​        别名就是我从url输入的路径会在别名里面判断是否存在，简单来说就是我多次定义一个path不同，但是component相同等其他相同的一个意思，我们不需要这样重复编写，而是通过别名来进行处理。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">const routes = [&#123; path: &#x27;/&#x27;, component: Homepage, alias: &#x27;/home&#x27; &#125;]</span><br></pre></td></tr></table></figure>

<p>​        使别名以 <code>/</code> 开头，以使嵌套路径中的路径成为绝对路径。你甚至可以将两者结合起来，用一个数组提供多个别名：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/users&#x27;,</span><br><span class="line">    component: UsersLayout,</span><br><span class="line">    children: [</span><br><span class="line">      // 为这 3 个 URL 呈现 UserList</span><br><span class="line">      // - /users</span><br><span class="line">      // - /users/list</span><br><span class="line">      // - /people</span><br><span class="line">      // /people 是绝对路径， list 是相对路径</span><br><span class="line">      &#123; path: &#x27;&#x27;, component: UserList, alias: [&#x27;/people&#x27;, &#x27;list&#x27;] &#125;,</span><br><span class="line">    ],</span><br><span class="line">  &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>​        如果你的路由有参数，请确保在任何绝对别名中包含它们：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/users/:id&#x27;,</span><br><span class="line">    component: UsersByIdLayout,</span><br><span class="line">    children: [</span><br><span class="line">      // 为这 3 个 URL 呈现 UserDetails</span><br><span class="line">      // - /users/24</span><br><span class="line">      // - /users/24/profile</span><br><span class="line">      // - /24</span><br><span class="line">      &#123; path: &#x27;profile&#x27;, component: UserDetails, alias: [&#x27;/:id&#x27;, &#x27;&#x27;] &#125;,</span><br><span class="line">    ],</span><br><span class="line">  &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>



<h2 id="路由组件传参"><a href="#路由组件传参" class="headerlink" title="路由组件传参"></a>路由组件传参</h2><h3 id="通过-props-true-传递给路由组件"><a href="#通过-props-true-传递给路由组件" class="headerlink" title="通过 props:true 传递给路由组件"></a>通过 props:true 传递给路由组件</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const User = &#123;</span><br><span class="line">  props: [&#x27;id&#x27;],</span><br><span class="line">  template: &#x27;&lt;div&gt;User &#123;&#123; id &#125;&#125;&lt;/div&gt;&#x27;</span><br><span class="line">&#125;</span><br><span class="line">const routes = [&#123; path: &#x27;/user/:id&#x27;, component: User, props: true &#125;]</span><br></pre></td></tr></table></figure>

<p>​        那么此时，id 就会通过props传递给路由组件</p>
<h3 id="命名视图-1"><a href="#命名视图-1" class="headerlink" title="命名视图"></a>命名视图</h3><p>​        对于有命名视图的路由，必须给props里面给每个命名视图定义配置</p>
<ul>
<li><p>如果直接使用 props: true，那么代表里面所有的都为true</p>
</li>
<li><p>否则就需要使用对象来对每个命名视图进行处理</p>
</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/user/:id&#x27;,</span><br><span class="line">    components: &#123; default: User, sidebar: Sidebar &#125;,</span><br><span class="line">    props: &#123; default: true, sidebar: false &#125;</span><br><span class="line">    // 所有的都为true</span><br><span class="line">    // props: true</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>



<h3 id="props使用对象"><a href="#props使用对象" class="headerlink" title="props使用对象"></a>props使用对象</h3><p>​        当 <code>props</code> 是一个对象时，它将原样设置为组件 props。当 props 是静态的时候很有用。</p>
<p>​        就是说，使用的是对象的话，那么对象里面的内容就会作为props传递给路由组件。同时如果此时你的路由组件是携带了参数的。那么将不会传递给路由组件了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/promotion/from-newsletter&#x27;,</span><br><span class="line">    component: Promotion,</span><br><span class="line">    props: &#123; newsletterPopup: false &#125;</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>



<h3 id="函数模式"><a href="#函数模式" class="headerlink" title="函数模式"></a>函数模式</h3><p>注意：</p>
<ul>
<li>对于函数，参数是route</li>
<li>返回值，如果是 Boolean 值，并不会变成 props: true 这两个并不是一个意思。所以不会起作用。</li>
<li>返回值，常是一个对象。然后按照对象的形式来处理</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">const routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#x27;/search&#x27;,</span><br><span class="line">    component: SearchUser,</span><br><span class="line">    props: route =&gt; (&#123; query: route.query.q &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>



<h2 id="不同的历史模式"><a href="#不同的历史模式" class="headerlink" title="不同的历史模式"></a>不同的历史模式</h2><h3 id="Hash模式"><a href="#Hash模式" class="headerlink" title="Hash模式"></a>Hash模式</h3><p>​        hash 模式是用 <code>createWebHashHistory()</code> 创建的：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">import &#123; createRouter, createWebHashHistory &#125; from &#x27;vue-router&#x27;</span><br><span class="line"></span><br><span class="line">const router = createRouter(&#123;</span><br><span class="line">  history: createWebHashHistory(),</span><br><span class="line">  routes: [</span><br><span class="line">    //...</span><br><span class="line">  ],</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>​        hash模式就是通过在url后面使用一个hash字符 #。然后因为哈希字符并不会发送到服务器，所以不会出现找不到url的情况。但是对于 SEO 和 看来说，确实有点影响。</p>
<h3 id="HTML5模式，history模式"><a href="#HTML5模式，history模式" class="headerlink" title="HTML5模式，history模式"></a>HTML5模式，history模式</h3><p>​        用 <code>createWebHistory()</code> 创建 HTML5 模式，推荐使用这个模式：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">import &#123; createRouter, createWebHistory &#125; from &#x27;vue-router&#x27;</span><br><span class="line"></span><br><span class="line">const router = createRouter(&#123;</span><br><span class="line">  history: createWebHistory(),</span><br><span class="line">  routes: [</span><br><span class="line">    //...</span><br><span class="line">  ],</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>​        当使用这种历史模式时，URL 会看起来很 “正常”，例如 <code>https://example.com/user/id</code>。漂亮!</p>
<p>​        不过，问题来了。由于我们的应用是一个单页的客户端应用，如果没有适当的服务器配置，用户在浏览器中直接访问 <code>https://example.com/user/id</code>，就会得到一个 404 错误。这就丑了。</p>
<p>​        不用担心：要解决这个问题，你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源，它应提供与你的应用程序中的 <code>index.html</code> 相同的页面。漂亮依旧!</p>
<p>​        简单来说就是，因为history模式的 url 是不带hash，所以我们知道从一个浏览器里面输入一个正常的url，他会找到对应的服务器并发送请求，那么类似于这种的： <a target="_blank" rel="noopener" href="https://example.com/usre/id">https://example.com/usre/id</a> 他就会先进入对应的。</p>
<h3 id="服务器配置实例"><a href="#服务器配置实例" class="headerlink" title="服务器配置实例"></a>服务器配置实例</h3><p>​        <strong>注意</strong>：以下示例假定你正在从根目录提供服务。如果你部署到子目录，你应该使用<a target="_blank" rel="noopener" href="https://cli.vuejs.org/config/#publicpath">Vue CLI 的 <code>publicPath</code> 配置</a>和相关的<a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/api/#createwebhistory">路由器的 <code>base</code> 属性</a>。你还需要调整下面的例子，以使用子目录而不是根目录（例如，将<code>RewriteBase/</code> 替换为 <code>RewriteBase/name-of-your-subfolder/</code>）。</p>
<h4 id="Apache"><a href="#Apache" class="headerlink" title="Apache"></a>Apache</h4><p>​        没有学过，可以说是完全看不懂了。</p>
<p>​        也可以使用 <a target="_blank" rel="noopener" href="https://httpd.apache.org/docs/2.2/mod/mod_dir.html#fallbackresource"><code>FallbackResource</code></a> 代替 <code>mod_rewrite</code>。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;IfModule mod_rewrite.c&gt;</span><br><span class="line">  RewriteEngine On</span><br><span class="line">  RewriteBase /</span><br><span class="line">  RewriteRule ^index\.html$ - [L]</span><br><span class="line">  RewriteCond %&#123;REQUEST_FILENAME&#125; !-f</span><br><span class="line">  RewriteCond %&#123;REQUEST_FILENAME&#125; !-d</span><br><span class="line">  RewriteRule . /index.html [L]</span><br><span class="line">&lt;/IfModule&gt;</span><br></pre></td></tr></table></figure>



<h4 id="nginx"><a href="#nginx" class="headerlink" title="nginx"></a>nginx</h4><p>​        实不相瞒，nginx，我也没有学过。。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">location / &#123;</span><br><span class="line">  try_files $uri $uri/ /index.html;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="原生-Node-js"><a href="#原生-Node-js" class="headerlink" title="原生 Node.js"></a>原生 Node.js</h4><p>​        简单来说，就是先建立监听。</p>
<p>​        然后使用 createServer，这个方法就会将所有的请求都会进行处理了。无论是什么请求，都会进行一个处理。那么我们思考这个算是一个拦截吗，因为既然什么请求都可以进行处理。那么就可以先做一个请求的拦截。当然，这样写符不符合规范不清楚。但是确实做拦截应该是可以的。</p>
<p>​        这里的内容就是，收到请求，然后将index文件里的内容进行读取，然后再通过写响应头，并将内容进行返回。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">const http = require(&#x27;http&#x27;)</span><br><span class="line">const fs = require(&#x27;fs&#x27;)</span><br><span class="line">const httpPort = 80</span><br><span class="line"></span><br><span class="line">http</span><br><span class="line">  .createServer((req, res) =&gt; &#123;</span><br><span class="line">    fs.readFile(&#x27;index.html&#x27;, &#x27;utf-8&#x27;, (err, content) =&gt; &#123;</span><br><span class="line">      if (err) &#123;</span><br><span class="line">        console.log(&#x27;We cannot open &quot;index.html&quot; file.&#x27;)</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      res.writeHead(200, &#123;</span><br><span class="line">        &#x27;Content-Type&#x27;: &#x27;text/html; charset=utf-8&#x27;,</span><br><span class="line">      &#125;)</span><br><span class="line"></span><br><span class="line">      res.end(content)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line">  .listen(httpPort, () =&gt; &#123;</span><br><span class="line">    console.log(&#x27;Server listening on: http://localhost:%s&#x27;, httpPort)</span><br><span class="line">  &#125;)</span><br></pre></td></tr></table></figure>



<h4 id="Express-Node-js"><a href="#Express-Node-js" class="headerlink" title="Express + Node.js"></a>Express + Node.js</h4><p>​        对于 Node.js/Express，可以考虑使用 <a target="_blank" rel="noopener" href="https://github.com/bripkens/connect-history-api-fallback">connect-history-api-fallback 中间件</a>。</p>
<p>后续还有很多其他的，但是因为其他的我连名字都没有听过了，所以就不写了，直接上官网链接。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://router.vuejs.org/zh/guide/essentials/history-mode.html</span><br></pre></td></tr></table></figure>



<h3 id="caveat"><a href="#caveat" class="headerlink" title="caveat"></a>caveat</h3><p>​        这有一个注意事项。你的服务器将不再报告 404 错误，因为现在所有未找到的路径都会显示你的 <code>index.html</code> 文件。为了解决这个问题，你应该在你的 Vue 应用程序中实现一个万能的路由来显示 404 页面。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">const router = createRouter(&#123;</span><br><span class="line">  history: createWebHistory(),</span><br><span class="line">  routes: [&#123; path: &#x27;/:pathMatch(.*)&#x27;, component: NotFoundComponent &#125;],</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>​        另外，如果你使用的是 Node.js 服务器，你可以通过在服务器端使用路由器来匹配传入的 URL，如果没有匹配到路由，则用 404 来响应，从而实现回退。查看 <a target="_blank" rel="noopener" href="https://v3.cn.vuejs.org/guide/ssr/introduction.html#what-is-server-side-rendering-ssr">Vue 服务器端渲染文档</a>了解更多信息。</p>
<p>​        这里，为什么使用 /:pathMatch(.*) 来匹配404呢，那是因为，这里路由的选择是一个按照分级来排名的。而这个写法的分数只有20分，基本可以说是，只有其他都匹配不上了，才会匹配上这个。</p>
<p>​        所以常用这个来匹配404路由。</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/02/04/CSS/css-hover%E5%92%8Cfocus%E9%A1%BA%E5%BA%8F/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/02/04/CSS/css-hover%E5%92%8Cfocus%E9%A1%BA%E5%BA%8F/" class="post-title-link" itemprop="url">css-hover和focus顺序</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-02-04 17:16:47" itemprop="dateCreated datePublished" datetime="2022-02-04T17:16:47+08:00">2022-02-04</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/CSS/" itemprop="url" rel="index"><span itemprop="name">CSS</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/CSS/%E9%9A%8F%E7%AC%94/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="hover和focus的顺序问题"><a href="#hover和focus的顺序问题" class="headerlink" title="hover和focus的顺序问题"></a>hover和focus的顺序问题</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">div:hover &#123; &#125;</span><br><span class="line">div:focus &#123; &#125;</span><br></pre></td></tr></table></figure>

<p>​        最近在写项目的时候无意间发现的问题，对于hover和触发和focus的触发问题。这个其实在学的时候就已经知道了，但是因为用的较少，所以还忘记了这个问题。</p>
<p>​        简单来说就是 hover需要放在focus的前面，因为hover的触发比focus触发的时机问题。会先focus然后再hover(应该)，但是在css里面，对于优先级相同的。在后面的会覆盖前面的。</p>
<p>​        通过这个我们也要知道关于冒泡和捕获触发的问题也要注意这个情况。事件是先捕获，然后再冒泡。</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/02/03/%E9%9A%8F%E7%AC%94/%E5%AD%97%E4%BD%93%E5%9B%BE%E6%A0%87%E7%9A%84%E5%88%B6%E4%BD%9C%E6%96%B9%E6%B3%95/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/02/03/%E9%9A%8F%E7%AC%94/%E5%AD%97%E4%BD%93%E5%9B%BE%E6%A0%87%E7%9A%84%E5%88%B6%E4%BD%9C%E6%96%B9%E6%B3%95/" class="post-title-link" itemprop="url">字体图标的制作方法</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-02-03 16:31:18" itemprop="dateCreated datePublished" datetime="2022-02-03T16:31:18+08:00">2022-02-03</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E9%9A%8F%E7%AC%94/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="字体图标的制作"><a href="#字体图标的制作" class="headerlink" title="字体图标的制作"></a>字体图标的制作</h1><p>​        首先。我们知道对于一个input输入框左右两边的一个小图标。一般会用一个常用的方法：字体图标 来进行显示。然后我们又从element ui的源码里面知道。字体图标是引入的。通过设置一个 font-face 来进行初始化一个 font-family。</p>
<p>​        那么我们此时就先知道一个事情。那就是如何使用字体图标。</p>
<p>​        但是我们此时就开始思考。那么这个字体图标是怎么进行显示的呢。</p>
<h2 id="字体图标的显示"><a href="#字体图标的显示" class="headerlink" title="字体图标的显示"></a>字体图标的显示</h2><p>​        我们通过查阅资料后，首先知道了，文字的显示是通过一个unicode码，进行的编译。unicode码又被叫做万国码。其中对于 e000 到 f8ff 这个返回作为用户的专用区，所以我们也可以发现。对于自定义的字体图标的content里面都是 \e217 等等这种样子的。</p>
<h2 id="字体图标的生成"><a href="#字体图标的生成" class="headerlink" title="字体图标的生成"></a>字体图标的生成</h2><p>​        通过上面我们知道了第一个，那就是字体图标是使用的自定义专区。</p>
<p>​        然后就是我们要知道的第二个，字体图标是怎么生成的。</p>
<p>​        这里我就简单的直说了。</p>
<p>​        字体图标的生成。我们只需要对应的svg图片。然后通过使用一个转换方法进行转换。这里我说一个 <strong>阿里巴巴矢量图标库</strong> 的网站，它这个网站可以上传图标。然后就会自动给你生成打包好。不需要你自己的操作。</p>
<h2 id="svg的制作"><a href="#svg的制作" class="headerlink" title="svg的制作"></a>svg的制作</h2><p>​        知道了字体图标的生成是通过svg进行的。那么我们只需要制作svg图标即可。这个也很方便。最简单的我们可以直接使用网站上进行svg制作。但是这样就没有那么好。制作的不会那么精良。那么我们也可以使用专业的制作软件，比例PS。等进行制作。</p>
<h2 id="字体图标的生成原理"><a href="#字体图标的生成原理" class="headerlink" title="字体图标的生成原理"></a>字体图标的生成原理</h2><p>​        暂未了解。</p>
<p>​        我们知道，字体图标是通过svg进行的转换。但是这个中间的转换方法我还没有了解。</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/02/02/JQuery/JQuery%E5%AD%A6%E4%B9%A0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/02/02/JQuery/JQuery%E5%AD%A6%E4%B9%A0/" class="post-title-link" itemprop="url">JQuery学习</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-02-02 19:53:24" itemprop="dateCreated datePublished" datetime="2022-02-02T19:53:24+08:00">2022-02-02</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JQuery/" itemprop="url" rel="index"><span itemprop="name">JQuery</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="学习"><a href="#学习" class="headerlink" title="学习"></a>学习</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">version: 3.6.0</span><br></pre></td></tr></table></figure>



<p>g: 4430</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">获取标签属性里面的data自定义属性</span><br><span class="line">function dataAttr( elem, key, data )</span><br><span class="line"></span><br><span class="line">这里的 replace 使用的是正则表达式，搭配的 $&amp;, 这里 $&amp; 代表了与 regexp 相匹配的子串。</span><br><span class="line">remutiDash 是 大写字母/g，意思就是说，将大写转为 中划线然后再用 toLowerCase 转为小写。</span><br><span class="line">name = &quot;data-&quot; + key.replace( rmultiDash, &quot;-$&amp;&quot; ).toLowerCase();</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/02/02/%E6%B5%8F%E8%A7%88%E5%99%A8/html%E6%A0%87%E7%AD%BE%E7%9A%84data-%E5%B1%9E%E6%80%A7/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/02/02/%E6%B5%8F%E8%A7%88%E5%99%A8/html%E6%A0%87%E7%AD%BE%E7%9A%84data-%E5%B1%9E%E6%80%A7/" class="post-title-link" itemprop="url">html标签的data-*属性</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-02-02 19:25:12" itemprop="dateCreated datePublished" datetime="2022-02-02T19:25:12+08:00">2022-02-02</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/HTML/" itemprop="url" rel="index"><span itemprop="name">HTML</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/HTML/%E9%9A%8F%E7%AC%94/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="什么是HTML标签的-data-属性"><a href="#什么是HTML标签的-data-属性" class="headerlink" title="什么是HTML标签的 data-* 属性"></a>什么是HTML标签的 data-* 属性</h1><p>​        通过对于图片懒加载的学习和requireJs中的一个了解。我们发现了一个处于标签中的一个属性data-*。那么这个属性是什么意思呢。</p>
<p>​        首先通过了解。我们知道了，data-*，这个属性是属于HTML5的一个新的特性。特点就是，可以通过这个方式给HTML标签添加新的属性。</p>
<h2 id="获取方式"><a href="#获取方式" class="headerlink" title="获取方式"></a>获取方式</h2><h3 id="使用-getAttribute进行获取"><a href="#使用-getAttribute进行获取" class="headerlink" title="使用 getAttribute进行获取"></a>使用 getAttribute进行获取</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">elem.getAttribute( name );</span><br></pre></td></tr></table></figure>



<h3 id="使用-HTML5-欣特性-dataset-进行获取"><a href="#使用-HTML5-欣特性-dataset-进行获取" class="headerlink" title="使用 HTML5 欣特性 dataset 进行获取"></a>使用 HTML5 欣特性 dataset 进行获取</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">elem.dataset.name 注意，使用 短横线命名的需要改为驼峰来进行取值。</span><br></pre></td></tr></table></figure>




      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/02/02/webpack/webpack%E5%AD%A6%E4%B9%A0%E4%B8%80/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/02/02/webpack/webpack%E5%AD%A6%E4%B9%A0%E4%B8%80/" class="post-title-link" itemprop="url">webpack学习一</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-02-02 18:53:38" itemprop="dateCreated datePublished" datetime="2022-02-02T18:53:38+08:00">2022-02-02</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/webpack/" itemprop="url" rel="index"><span itemprop="name">webpack</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="webpack-学习"><a href="#webpack-学习" class="headerlink" title="webpack 学习"></a>webpack 学习</h1><h2 id="模块化"><a href="#模块化" class="headerlink" title="模块化"></a>模块化</h2><p>​        首先，对于模块化，我们可以知道的一个是 node.js 作为一个后端的一个JavaScript，可以使用 require。但是这个不能在浏览器上面进行使用。</p>
<p>​        此时我们可以使用一个requireJs的一个方法来进行一个实现。可以在浏览器上面进行调用</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">大致就是 </span><br><span class="line">第一个是需要调用其他js文件的位置，是一个数组，代表了可以传递很多。 ./requireJs/add.js 。。</span><br><span class="line">第二个是一个回调函数，回调函数的参数是从你的 引入的 文件里面那个回调函数的执行的返回值作为的一个参数。同时参数的顺序取决于第一个数组的顺序。</span><br><span class="line">define([], function() &#123;</span><br><span class="line">	return callFn</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<img src="/.io//image-20220202191750607.png" alt="image-20220202191750607" style="zoom:50%;">



<p>定义一个 data-main的位置，代表了需要从哪进行执行。</p>
<img src="/.io//image-20220202191837055.png" alt="image-20220202191837055" style="zoom:80%;">

<p>最后进行执行调用。</p>
<p><img src="/.io//image-20220202191945426.png" alt="image-20220202191945426"></p>
<p>这里的 data-* 是html5 的一个新的语法。同时图片懒加载也是运用了这个语法来存储图片的真正的src路径。</p>
<p>​        使用 script 的 type，设置type为module，然后使用 import进行导入</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import add from &#x27;./esm/add.js&#x27;</span><br></pre></td></tr></table></figure>

<p>​        同时，如果使用 file 的方法去浏览器进行访问。那么及那个不能进行获取其他文件的内容。因为此时这个产生了跨域的请求。需要创建一个 http-server。</p>
<p>​        可以使用 npx http-server 进行启动</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/01/29/elementUI%E6%BA%90%E7%A0%81/elementUI%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90(%E4%B8%80)/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/01/29/elementUI%E6%BA%90%E7%A0%81/elementUI%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90(%E4%B8%80)/" class="post-title-link" itemprop="url">elementUI源码分析(一)</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-01-29 17:18:30" itemprop="dateCreated datePublished" datetime="2022-01-29T17:18:30+08:00">2022-01-29</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/elementUI/" itemprop="url" rel="index"><span itemprop="name">elementUI</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="elementUI-源码分析"><a href="#elementUI-源码分析" class="headerlink" title="elementUI 源码分析"></a>elementUI 源码分析</h1><p>​    最近想学一下如何写一个组件，所以学习一下elementUI的源码，大概有一个基本的了解。</p>
<h2 id="入口-package-json"><a href="#入口-package-json" class="headerlink" title="入口 package.json"></a>入口 package.json</h2><p>​    主要的几个地方</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">main，定义一个入口文件，默认值是模块根目录的index.js</span><br><span class="line">style，打包工具通过style知道了样式文件的打包位置</span><br></pre></td></tr></table></figure>



<h2 id="src-index-js"><a href="#src-index-js" class="headerlink" title="src/index.js"></a>src/index.js</h2><p>​    我们看一下 src的index</p>
<p>​    其实大致的意思就是，先进行组件的引入，然后将引入的组件合并为一个数组，然后创建一个 install 方法。里面的核心就是 Vue.component 方法。最后在export 导出组件和install方法。</p>
<p>​    install方法为什么需要呢，因为在调用 Vue.use 时，如果插件是一个对象，那么就会查找里面的install方法。如果插件是一个函数，那么就会作为install方法进行调用。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">import xx from &#x27;xxx&#x27;</span><br><span class="line"></span><br><span class="line">const c = [</span><br><span class="line">	xx</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line">const install = function(Vue, opts = &#123;&#125;) &#123;</span><br><span class="line">	c.forEach(v =&gt; &#123;</span><br><span class="line">		Vue.component(v.name, v)</span><br><span class="line">	&#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export default &#123;</span><br><span class="line">	install,</span><br><span class="line">	</span><br><span class="line">	xx</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里，我个人觉得使用 对象来代替数组进行存储。可以将后续的export default 使用解构赋值来进行代替。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">const c = &#123;</span><br><span class="line">	xx</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">const install = function(Vue, opts = &#123;&#125;) &#123;</span><br><span class="line">	for (const key in c) &#123;</span><br><span class="line">		Vue.component(key, c[key])</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export default &#123;</span><br><span class="line">	install,</span><br><span class="line">	</span><br><span class="line">	...c</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="组件的文件格式"><a href="#组件的文件格式" class="headerlink" title="组件的文件格式"></a>组件的文件格式</h2><p>创建一个目录，然后创建一个index.js文件作为一个入口，创建一个src文件夹作为组件的存放。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">xx</span><br><span class="line">	src</span><br><span class="line">		xx.vue</span><br><span class="line">	index.js</span><br></pre></td></tr></table></figure>



<h3 id="index-js"><a href="#index-js" class="headerlink" title="index.js"></a>index.js</h3><p>其中，index.js 才是比较重要的一个部分</p>
<p>因为在使用 from 进行引入时，如果是一个目录，那么默认就会去查找index.js文件，当然如果配置了package.json的入口会不一样。</p>
<p>​    index.js的内容，简单来说就是创建了一个install方法。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">import xx from &#x27;../src/xx&#x27;</span><br><span class="line"></span><br><span class="line">xx.install = function(Vue) &#123;</span><br><span class="line">	Vue.component(xx.name, xx)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export defalt xx</span><br></pre></td></tr></table></figure>



<h2 id="index-scss"><a href="#index-scss" class="headerlink" title="index.scss"></a>index.scss</h2><p>​        在 package/theme-chalk/src 里面。</p>
<p>​        common，里面创建一个 var.scss 里面存储了一些公用的变量。其他地方需要时要引入 var.scss</p>
<p>​        以及在一个index.scss 里面进行一个引入。</p>
<p>​        然后再看看 element ui的官网。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">import &#x27;element-ui/lib/theme-chalk/index.css&#x27;;</span><br><span class="line">这个里面就是存储了全局的css，然后进行一个引入。</span><br></pre></td></tr></table></figure>

<p>​        并且将icon.scss 进行了引入，然后通过全局引入index来引入的icon。</p>
<p>​        原因：</p>
<ul>
<li><p>因为 iconfont 的引入是需要使用url的引入</p>
<ul>
<li>```<br>src: url(‘./fonts/iconfont.ttf?t=1643365814886’) format(‘truetype’);<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">* 同时对于引用的一个问题。那就是如果我在input目录下的index.scss 进行引入。那么对应的需要将引入的url路径进行改变，例子：url(&#x27;../fonts/iconfont.ttf&#x27;)</span><br><span class="line"></span><br><span class="line">  * 因为执行文件在这个目录，所以最终scss编译为css的时候会将路径引入在这里。所以会出现问题，所以Elem UI 的方法是将其在外面创建一个index.scss，然后只需要引入这个index.scss，即可。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
fonts<br>iconfont.ttf<br>input<br>index.scss<br>icon.scss<br>index.scss<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">## fonts-icon</span><br><span class="line"></span><br></pre></td></tr></table></figure>
package/theme-chalk/src/icon.scss<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">* 首先，这个fonts-icon 是使用的 font class 这个方法，具体的几个方法。我们可以通过去 阿里巴巴矢量图标库下载时，使用下载代码，查看demo的html来进行查看区分。</span><br><span class="line"></span><br><span class="line">* 使用 @font-face 进行初始化。这个参数需要进行了解。这个大概就是说，指定一个font-family的名称，以及指定一个url代表了可以去哪进行获取。</span><br><span class="line">  * 使用 #&#123;$xx&#125; 让 路径成为一个变量。</span><br><span class="line">* 然后使用类名选择器进行查找类名，将对应类名的进行初始化项目。</span><br><span class="line">* 目录构架，创建一个fonts的文件夹，用来存放 tff 和 字体的 js wtff 等文件，然后在外面创建一个icon的scss文件，用来进行使用。</span><br><span class="line">* 然后对要调用的使用类进行调用，然后类将同一进行一个css选择器进行初始化和选择。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">​		这里我们看一下代码</span><br><span class="line"></span><br></pre></td></tr></table></figure>
[class^=”el-icon-“], [class*=” el-icon-“] {    }<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		这是element 写的选择器的选择，这两个选择器分别代表 选择从 el-icon- 开始 或者 包含了 &#x27; el-icon-&#x27;，这里，你可能会有思考，为什么需要分开，如果我直接使用 class*=&quot;el-icon-&quot; 这个不就是包含了吗。开始我也在思考，然后我发现了。因为 *= 是包含。那么如果用户自己定义的类名是 xxel-icon- 那么也会被我们这个包含进去，所以 这个就是需要进行分开，代表了是一个独立的class。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">## input</span><br><span class="line"></span><br></pre></td></tr></table></figure>
package/inpu<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		Elem UI 使用 input的方法是。首先，通过type进行类型的决定，并且支持 textarea 类型。</span><br><span class="line"></span><br><span class="line">​		输入框包含了 前/后 置元素 和 内容。 内容就是显示在输入框里面内部的icon等。 元素就是显示在输入框前面的。和输入框紧邻的一个样式。 </span><br><span class="line"></span><br><span class="line">​		同时，禁用了组件的继承，然后将属性全部赋值于input 输入框里面，方便用于进行透明化的处理。这个常用于封装组件，并且组件的核心不处于根组件的情况。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
v-bind=”$attrs”</li>
</ul>
</li>
</ul>
<p>inheritAttrs: false</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		同时 Elem UI 的密码框是通过使用 show-password 进行的操作。</span><br><span class="line"></span><br><span class="line">### icon 部分</span><br><span class="line"></span><br><span class="line">​		并且使用了 前置内容 和 后置内容 通过使用 prefixIcon 和 suffixIcon 来进行设置。并且在里面同时也设置了 插槽。可以使用插槽的形式来配置前置和后置 内容。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><slot name="prefix"></slot><br><i class="el-input__icon" v-if="prefixIcon" :class="prefixIcon"><br></i></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">​		使用了 v-if 对于没有使用icon的进行了 隐藏。</span><br><span class="line"></span><br><span class="line">​		如果使用了 prefixIcon 进行了图标，或者 $slots.prefix 插槽。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>span<br>    v-if=”prefixIcon || $slots.prefix”</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">### input事件部分</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>@compositionstart=”handleCompositionStart”<br>@compositionupdate=”handleCompositionUpdate”<br>@compositionend=”handleCompositionEnd”<br>@input=”handleInput”<br>@focus=”handleFocus”<br>@blur=”handleBlur”<br>@change=”handleChange”</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">**这里的问题点：** </span><br><span class="line"></span><br><span class="line">* 我们为什么不使用 $listeners 进行封装。</span><br><span class="line"></span><br><span class="line">* 我们可以知道，默认情况下，进行组件方法的监听会加载入根组件</span><br><span class="line"></span><br><span class="line">* 但是，因为组件内部的根组件不是input，所以对于监听一个原生的方法。我们使用.native。</span><br><span class="line"></span><br><span class="line">* 并且直接监听给根组件并不会被当作一个原生的监听方法。对于根组件的监听，我们就可以通过 $listeners 进行监听。</span><br><span class="line"></span><br><span class="line">* 那么我好奇，如果我 使用 v-model，然后，组件内部使用 v-bind=&#x27;$attrs&#x27; v-on=&quot;$listeners&quot; 那么是不是就应该也有对应的效果啊。</span><br><span class="line"></span><br><span class="line">* 当然事实是不行，因为数据返回是一个 input event 事件。所以我看到了vue 官网是使用的 this.$emit(&#x27;input&#x27;, event.target.value) 然后就可以了。</span><br><span class="line"></span><br><span class="line">* 虽然这里，可以使用 v-model 了，但是，有另一个问题，那就这样写，自身的input事件会不一样。</span><br><span class="line"></span><br><span class="line">  * 首先 使用 @input=&quot;xxFn&quot; 此时的第一个参数不是event事件了，而是子组件传递过来的参数</span><br><span class="line">  * 其次，如果我们使用 focus.native 那么就会失败。但是因为input是一个可冒泡事件，所以input使用没有问题。</span><br><span class="line"></span><br><span class="line">* 同时注意，此时的$event 是子组件传递的数据了。</span><br><span class="line"></span><br><span class="line">  * ```</span><br><span class="line">    inputListeners: function () &#123;</span><br><span class="line">      var vm = this</span><br><span class="line">      // `Object.assign` 将所有的对象合并为一个新对象</span><br><span class="line">      return Object.assign(&#123;&#125;,</span><br><span class="line">        // 我们从父级添加所有的监听器</span><br><span class="line">        this.$listeners,</span><br><span class="line">        // 然后我们添加自定义监听器，</span><br><span class="line">        // 或覆写一些监听器的行为</span><br><span class="line">        &#123;</span><br><span class="line">          // 这里确保组件配合 `v-model` 的工作</span><br><span class="line">          input: function (event) &#123;</span><br><span class="line">            vm.$emit(&#x27;input&#x27;, event.target.value)</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;</span><br><span class="line">      )</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    v-on=&quot;inputListeners&quot;</span><br><span class="line">    </span><br><span class="line">    父组件的调用</span><br><span class="line">    方法</span><br><span class="line">    @input=&quot;inputFn(&#x27;$event&#x27;, $event)&quot;</span><br><span class="line">    inputFn(event, e) &#123;</span><br><span class="line">      console.log(&#x27;event&#x27;, event, e) // $event, value</span><br><span class="line">    &#125;,</span><br></pre></td></tr></table></figure>

<p><strong>Elem UI input 的监听事件之 compositionstart</strong>： </p>
<p>通过使用 isComposing 来判断是否处于中文输入情况。对于中文的输入不会提交，不会进行验证和发送。</p>
<p>其中我们发现在update的时候，调用了一个 isKorean 这里的方法就是里面有一个正则判断来判断你的输入是不是韩文的。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const text = event.target.value;</span><br><span class="line">const lastCharacter = text[text.length - 1] || &#x27;&#x27;;</span><br><span class="line">this.isComposing = !isKorean(lastCharacter);</span><br><span class="line"></span><br><span class="line">判断是不是韩文。</span><br><span class="line">export function isKorean(text) &#123;</span><br><span class="line">  const reg = /([(\uAC00-\uD7AF)|(\u3130-\u318F)])+/gi;</span><br><span class="line">  return reg.test(text);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>​        同时我发现，Elem UI对于 compositionstart 事件没有进行 emit 提交。所以我这里给我的UI做了一个提交。不知道是不是应该有个什么问题。</p>
<p>​        同时，注意Elem UI input并没有对date进行封装样式，只是另写了一个组件给的date样式，内部input实则还是String。</p>
<p>​        输入框的 清除框通过v-if进行的判断显示隐藏。通过focus事件和mouseenter和mouseleave来解决 focus 和 hover 的值。</p>
<p>输入框的 placeholder 样式使用的 scss的 mixin 和 content 进行的混入。</p>
<h2 id="style-sass"><a href="#style-sass" class="headerlink" title="style sass"></a>style sass</h2><p>​        样式的编写。</p>
<h3 id="对于-placeholder"><a href="#对于-placeholder" class="headerlink" title="对于 placeholder"></a>对于 placeholder</h3><p>​        使用 混入 和 content 进行了 一次 封装，后续只需要混入 这个placeholder 方法就可以进行处理。当然，我发现对于input貌似不需要使用这个混入，直接使用 ::placeholder 这个方法就可以。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">@mixin placeholder &#123;</span><br><span class="line">  &amp;::-webkit-input-placeholder &#123;</span><br><span class="line">    @content</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  &amp;::-moz-placeholder &#123;</span><br><span class="line">    @content</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  &amp;:-ms-input-placeholder &#123;</span><br><span class="line">    @content</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="disabled"><a href="#disabled" class="headerlink" title="disabled"></a>disabled</h3><p>​        同时使用混入进行disabled的方法的处理。</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/01/22/%E9%9A%8F%E7%AC%94/npm-package%E4%B8%8A%E4%BC%A0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/01/22/%E9%9A%8F%E7%AC%94/npm-package%E4%B8%8A%E4%BC%A0/" class="post-title-link" itemprop="url">npm-package上传</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-01-22 23:02:31" itemprop="dateCreated datePublished" datetime="2022-01-22T23:02:31+08:00">2022-01-22</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E9%9A%8F%E7%AC%94/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="npm包上传到npm官网"><a href="#npm包上传到npm官网" class="headerlink" title="npm包上传到npm官网"></a>npm包上传到npm官网</h1><p>众所周知，我们可以使用npm i xxx进行下载，npm作为一个包管理的一个工具，我们可以使用别人的包，我们也可以自己在npm上面创建一个属于自己的包，然后使用npm进行下载</p>
<h2 id="首先，肯定是要在-npm-官网上面创建一个账号了"><a href="#首先，肯定是要在-npm-官网上面创建一个账号了" class="headerlink" title="首先，肯定是要在 npm 官网上面创建一个账号了"></a>首先，肯定是要在 npm 官网上面创建一个账号了</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://www.npmjs.com/</span><br></pre></td></tr></table></figure>



<h2 id="然后就是-进入-cmd在本地进行登录"><a href="#然后就是-进入-cmd在本地进行登录" class="headerlink" title="然后就是 进入 cmd在本地进行登录"></a>然后就是 进入 cmd在本地进行登录</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">使用 npm login 就可以进行登录</span><br></pre></td></tr></table></figure>

<p>注意点：</p>
<p>​    这个需要在官网，所以你要知道你现在连接的仓库是</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://registry.npmjs.org/</span><br></pre></td></tr></table></figure>

<p>​    当然我记得现在比较新的npm应该是在登录的时候可以看到自己登录的网站是哪个，</p>
<p>​    如果看不到自己的网站是哪个，那么我们可以使用一个包管理工具 nrm 进行管理</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">npm i -g nrm</span><br><span class="line"></span><br><span class="line">nrm ls</span><br><span class="line">nrm use npm</span><br></pre></td></tr></table></figure>

<p>然后使用</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm login</span><br><span class="line"></span><br><span class="line">输入自己的用户名和密码，然后输入邮箱</span><br></pre></td></tr></table></figure>



<h2 id="初始化一个包"><a href="#初始化一个包" class="headerlink" title="初始化一个包"></a>初始化一个包</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">npm init</span><br><span class="line"></span><br><span class="line">对应的意思是</span><br><span class="line">包名</span><br><span class="line">版本，听说需要从 0.0.1 开始</span><br><span class="line">描述</span><br><span class="line">入口文件</span><br><span class="line">测试指令：应该是，这个没有用过</span><br><span class="line">git 仓库</span><br><span class="line">关键字，可以用于搜索</span><br><span class="line">作者</span><br><span class="line">证书，用MIT，开源管理不会过于严格，不会引起应激反应</span><br><span class="line">然后就是回车回车完事儿</span><br></pre></td></tr></table></figure>

<p><img src="/.io//image-20220122231048580.png" alt="image-20220122231048580"></p>
<h2 id="编写自己的包的过程"><a href="#编写自己的包的过程" class="headerlink" title="编写自己的包的过程"></a>编写自己的包的过程</h2><p>xxxx</p>
<p>然后包编写完了，就是开始上传了</p>
<h2 id="最后，上传"><a href="#最后，上传" class="headerlink" title="最后，上传"></a>最后，上传</h2><p>这个很简单，就是publish就完了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm publish</span><br></pre></td></tr></table></figure>



<h2 id="更新-npm"><a href="#更新-npm" class="headerlink" title="更新 npm"></a>更新 npm</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">就是修改一下 version</span><br><span class="line">然后 npm publish 就行</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2022/01/22/JavaScript/JavaScript%E5%AE%9A%E6%97%B6%E5%99%A8/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2022/01/22/JavaScript/JavaScript%E5%AE%9A%E6%97%B6%E5%99%A8/" class="post-title-link" itemprop="url">JavaScript定时器</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-01-22 19:28:13" itemprop="dateCreated datePublished" datetime="2022-01-22T19:28:13+08:00">2022-01-22</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/" itemprop="url" rel="index"><span itemprop="name">JavaScript</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/%E9%9A%8F%E7%AC%94/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="JavaScript-定时器"><a href="#JavaScript-定时器" class="headerlink" title="JavaScript 定时器"></a>JavaScript 定时器</h1><p>​        简单来说问题：定时器执行结束了也不是null，所以在 防抖和节流上面需要进行一个处理。</p>
<p>​        这里就简单的提几句。常用的两个</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">setTimeout</span><br><span class="line">clearTimeout</span><br><span class="line"></span><br><span class="line">setInterval</span><br><span class="line">clearInterval</span><br></pre></td></tr></table></figure>



<h2 id="settimeout在执行之后，timer也不会清空的"><a href="#settimeout在执行之后，timer也不会清空的" class="headerlink" title="settimeout在执行之后，timer也不会清空的"></a>settimeout在执行之后，timer也不会清空的</h2><p>都会执行，代表了，执行之后，timer不清空</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">let timer = settimeout(() =&gt; &#123;&#125;, 1)</span><br><span class="line"></span><br><span class="line">然后再延时执行下面方法，也会出现输出</span><br><span class="line">log.timer</span><br><span class="line">if (timer) log.1</span><br><span class="line">timer &amp;&amp; log.2</span><br></pre></td></tr></table></figure>



<h2 id="cleartimeout清除之后-timer依然判断为true"><a href="#cleartimeout清除之后-timer依然判断为true" class="headerlink" title="cleartimeout清除之后 timer依然判断为true"></a>cleartimeout清除之后 timer依然判断为true</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">cleartimeout(timer)</span><br><span class="line"></span><br><span class="line">然后再延时执行下面方法, 同上</span><br><span class="line">log.timer</span><br><span class="line">if (timer) log.1</span><br><span class="line">timer &amp;&amp; log.2</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/page/3/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/page/5/">5</a><span class="space">&hellip;</span><a class="page-number" href="/page/11/">11</a><a class="extend next" rel="next" href="/page/5/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>

</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">tallgy</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script>

  





  





</body>
</html>
